import asyncio
import functools
from pathlib import Path
from urllib.parse import quote, unquote

import requests

from src.allview.functions import parse_text
from src.common.constant import PROJECT_URL
from src.singletone.session_singleton import SessionSingleton


class AllViews(object):
    from src.decoators.functions_decorator import exc_decorator, check_session_decorator, fill_up_args_decorator, \
        error_msg_decorator

    def __init__(self):
        self.timeout = 30
        self.session = SessionSingleton().session
        self.loop = asyncio.get_event_loop()

    # 登陆
    @exc_decorator(retry_exceptions=(requests.exceptions.RequestException, ValueError), max_retries=5)
    def _login(self, **kwargs):
        # session = session if session else requests.session()
        username = kwargs.get("username", "13392790627")
        password = kwargs.get("password", "123456789")
        captcha = kwargs.get("captcha", "111111")
        post = {
            "ISMOBILE": "false",
            "YGGH": username,
            "YGMM": password,
            "yzm": captcha,
        }
        response = self.session.post(PROJECT_URL['login'], data=post, timeout=self.timeout)
        if "欢迎回来" not in response.text:
            raise ValueError("Login failed,please check your username and password")
        import time
        SessionSingleton().session_build_time = int(time.time() * 1000)

    @check_session_decorator
    def _logout(self, **kwargs):
        self.session.post(url="http://132.110.64.76:8080/allview/logout.jsp")

    # 新增派单活动
    @exc_decorator()
    @check_session_decorator
    @fill_up_args_decorator
    @error_msg_decorator
    async def add_action(self, *args, **kwargs):
        post = {
            "WP_ID": "",
            "WP_NAME": "",  # 必填
            "WP_CODE": "jqrcs20180730765432",  # 必填
            "DAY_COUNT": "",
            "WP_PACKAGE": "C",  # 必填
            "REMARK": "",
            "CALIBER": "",
            "PARAM_NAMES": "",
            "DEAL_FIELDS": "ACC_NBR",  # 必填
            "DATE_MA_BEGIN": "2018-08-29",  # 必填
            "DATE_MA_END": "2018-08-29",  # 必填
            "DATE_STAT_BEGIN": "2018-08-29",  # 必填
            "DATE_STAT_END": "2018-08-29",  # 必填
        }
        # 更新参数(下同)
        post.update(**kwargs)
        # 提交请求
        response = await self.loop.run_in_executor(None,
                                                   functools.partial(self.session.post, url=PROJECT_URL['wp_main_save'],
                                                                     data=post, timeout=self.timeout))
        # response = self.session.post(PROJECT_URL['wp_main_save'], data=post, timeout=self.timeout)
        # print(response.text)
        # xpath的封装
        wp_id = parse_text(response, '//input[@id="WP_ID"]/@value')
        wp_type = parse_text(response, '//input[@id="WP_TYPE"]/@value')
        if response.status_code != 200:
            raise Exception("添加活动发生HTTP错误 (STATE CODE:{})".
                            format(response.status_code))
        if "抱歉！本站无法执行此请求" in response.text:
            raise Exception("添加活动失败,活动名称可能已存在或其他错误!")
        if 'myTab' not in response.text:
            raise Exception("添加活动失败,请重试!")
        return wp_id, wp_type

    # 添加营销政策
    @exc_decorator()
    @check_session_decorator
    @fill_up_args_decorator
    @error_msg_decorator
    async def add_sales_rmd(self, *args, **kwargs):
        wp_id, wp_type = args
        success_source_code = kwargs.get("success_source_code", "")
        false_source_code = kwargs.get("false_source_code", "")
        post = {
            'oper': 'add',
            'WP_ID': wp_id,  # 必填
            'J_ID': '',
            'SALES_RMD': quote('机器人测试开头才行'),  # 必填
            'JUDGE_ORDER': '03',  # 必填
            'JUDGE_TYPE': 'Z',  # 必填
            'IMPORTANCE': 'Y',  # 必填
        }
        post.update(**kwargs)
        # 以下2字段电信才有，外系统没有
        if not any(success_source_code) and "SUCCESS_SOURCE_CODE" in post.keys():
            post.pop("SUCCESS_SOURCE_CODE")
        if not any(false_source_code) and "FALSE_SOURCE_CODE" in post.keys():
            post.pop("FALSE_SOURCE_CODE")
        response = await self.loop.run_in_executor(None,
                                                   functools.partial(self.session.post,
                                                                     url=PROJECT_URL['wp_judge_save'],
                                                                     data=post, timeout=self.timeout))
        # response = self.session.post(PROJECT_URL['wp_judge_save'], data=post, timeout=self.timeout)
        # 获取json
        result_json = response.json(encoding="gb18030")
        error = result_json.get("error", "-1")
        if error != '1':
            raise Exception(error)
        j_id = result_json.get("jid", "")
        return j_id

    # 添加，修改参数
    @exc_decorator()
    @check_session_decorator
    @fill_up_args_decorator
    @error_msg_decorator
    async def wp_params_save(self, *args, **kwargs):
        wp_id, = args
        post = {
            "WP_ID": wp_id,  # variable
            "PARAM_NAMES": "",
            "PARAM_SOURCES": "",
        }
        post.update(**kwargs)
        response = await self.loop.run_in_executor(None,
                                                   functools.partial(self.session.post,
                                                                     url=PROJECT_URL['wp_param_save'],
                                                                     data=post, timeout=self.timeout))
        # response = self.session.post(PROJECT_URL["wp_param_save"], data=post, timeout=self.timeout)
        result = response.json()
        error = result.get("error", "1")
        if error != '1':
            raise Exception(error)

    # 新增，修改批次
    @exc_decorator()
    @check_session_decorator
    @fill_up_args_decorator
    @error_msg_decorator
    async def wp_batch_save(self, *args, **kwargs):
        wp_id, j_id = args
        # 下载csv

        # if any(network_file_uri):
        #     response = requests.get(network_file_uri)
        #     with open("file.csv", "wb") as f:
        #         f.write(response.content)
        post = {
            "oper": "add",
            "COMMIT_TYPE": "SI",
            "AUTO_WP": "Y",  # variable
            "AUTO_WP_TYPE": "S,J,A",
            "WP_ID": wp_id,  # variable
            "BATCH_NAME": quote("看看这自动批次添加成功不12"),
            "B_ID": "",
            "JUDGE_ID": j_id,  # 必填 新增添空
            "DATE_MA_BEGIN": "2018-08-03",
            "DATE_MA_END": "2018-08-20",
            "DATE_STAT_BEGIN": "2018-08-15",
            "DATE_STAT_END": "2018-08-30",
            "IMPORT_MODE": "C",
            "IMPORT_SQL": "",
            "EMPTY_DATA": "T",
            "TRIGGER_ID": "",
            "RETRY_TRIGGER_ID": "",
            "IGNORE": "N",
        }

        path = unquote(kwargs.pop("PATH", ""))
        file_name = Path(path).name
        files = {"demoFile": (file_name, open(path, "rb"), "application/octet-stream")}
        post.update(**kwargs)

        response = await self.loop.run_in_executor(None,
                                                   functools.partial(self.session.post,
                                                                     url=PROJECT_URL['wp_batch_save'],
                                                                     data=post, files=files, timeout=self.timeout))
        result = response.json()
        error = result.get("error", "1")
        if error != "1":
            raise Exception(error)

    # 新增反馈定义
    @exc_decorator()
    @check_session_decorator
    @fill_up_args_decorator
    @error_msg_decorator
    async def wp_record_save(self, *args, **kwargs):
        wp_id, = args
        post = {
            "oper": "add",
            "WP_ID": wp_id,
            "RC_ID": "",
            "PARAM_NAME": quote("关键决策人"),
            "PARAM_TYPE": "S",
            "COL_TYPE": "E",
            "REQUIRED": "Y",
            "COL_DEFAULT": " ",
            "GROUP_NAME": quote("回填信息"),
            "ORDER_BY": "2",
            "MODIFY_DAY": "3",
            "DEPEND_ON": "",
            "DEPEND_RC_ID": "",
            "DEPEND_VALUE": "",
            "COL_SELECT_SQL": "",
        }
        d = await self.verify_depend_rc_id(wp_id, **kwargs)
        post.update(**d)
        response = await self.loop.run_in_executor(None,
                                                   functools.partial(self.session.post,
                                                                     url=PROJECT_URL['wp_record_save'],
                                                                     data=post, timeout=self.timeout))
        # response = self.session.post(PROJECT_URL["wp_record_save"], data=post, timeout=self.timeout)
        result = response.json()
        error = result.get("error", "1")
        if error != "1":
            raise Exception(error)

    @exc_decorator()
    @check_session_decorator
    @error_msg_decorator
    async def verify_depend_rc_id(self, wp_id, **kwargs):
        depend_rc_id = kwargs.get("DEPEND_RC_ID", "")
        if any(depend_rc_id):
            post = {
                "WP_ID": wp_id,
                "TYPE": "editSearch"
            }
            response = await self.loop.run_in_executor(None,
                                                       functools.partial(self.session.post,
                                                                         url=PROJECT_URL["wp_record_search"],
                                                                         data=post, timeout=self.timeout))
            status_code = response.status_code
            if status_code != 200:
                raise Exception("请求依赖值列表失败,status_code:{}".format(status_code))
            result = response.json()
            param_list = result.get("paraName", [])
            if not any(param_list):
                raise Exception("无法找到依赖值 {}".format(depend_rc_id))
            rc_id = {"DEPEND_RC_ID": item["RC_ID"] for item in param_list if depend_rc_id in item.values()}
            kwargs.update(**rc_id)
        return kwargs
